<?php
/*********************************************
  Copyright (c) 2011 by DragonflyCMS
  http://dragonflycms.org
  Released under GNU GPL version 2 or any later version

  $Source$
  $Revision$
  $Author$
  $Date$
**********************************************/

class Module
{

	public $sides, $title;

	public static $custom = array();
	protected static $allow_access = array();

	/* read only */
	protected $active, $cat_id, $chroot, $file, $in_home, $https = true, $inmenu;
	protected $mid, $name, $name_lc, $pos, $uninstall, $version, $view;

	private $data = array(), $list = array();

	public function __get($p) {
		switch ($p) {
			case 'active':
			case 'cat_id':
			case 'chroot':
			case 'file':
			case 'in_home':
			case 'inmenu':
			case 'mid':
			case 'name':
			case 'name_lc':
			case 'pos':
			case 'sides':
			case 'uninstall':
			case 'version':
			case 'view':
				return $this->$p;
			default: return;
		}
	}

	# $name: the module name, case insensitive
	# $file: file to request inside the module, case insensitive
	# $http: true to look in http request, false to create a virtual module and access all its informations
	public function __construct($name, $file, $http=true)
	{
		global $MAIN_CFG;
		$default = ('op' === $name && defined('ADMIN_PAGES')) ? 'index' : $MAIN_CFG['global']['main_module'];
		if ($http) {
			$this->name = !empty($_GET[$name]) ? $_GET[$name] : (!empty($_POST[$name]) ? $_POST[$name] : $default);
			$this->file = !empty($_GET[$file]) ? $_GET[$file] : (!empty($_POST[$file]) ? $_POST[$file] : 'index');
		} else {
			$this->name = $name;
			$this->file = $file;
		}
		if (!preg_match('#^[a-z][a-z0-9_\-]+$#i', $this->name)) {
			cpg_error(sprintf(_ERROR_BAD_CHAR, strtolower(_MODULES)), 400);
		}
		if (!preg_match('#^[a-z][a-z0-9_\-]+$#i', $this->file)) {
			cpg_error(sprintf(_ERROR_BAD_CHAR, strtolower(_BLOCKFILE2)), 400);
		}

		if ('op' === $name && defined('ADMIN_PAGES')) { $this->loadAdmin(); } else { $this->loadModule(); }
	}

	# Create a new object as, $Example = new Module('example'), tip use module name for new objects
	# Fatal error check: $Example->allow()
	# Skip fatal error with $Example->allow(true)
	public function allow($check=false)
	{
		if (can_admin() || $this->in_home || 'Your_Account' === $this->name || in_array($this->name, self::$allow_access)) { return true; }
		if (!$this->active && !can_admin($this->name_lc)) {
			$error = sprintf(_MODULENOEXIST, '');
		}
		elseif (1 === $this->view && !is_user()) {
			global $MAIN_CFG;
			$error = _MODULEUSERS.($MAIN_CFG['member']['allowuserreg'] ? _MODULEUSERS2 : '' );
		}
		elseif (2 === $this->view && !can_admin($this->name)) {
			$error = _MODULESADMINS;
		}
		elseif (3 < $this->view && !in_group($this->view-3)) {
			global $db, $prefix;
			list($groupName) = $db->sql_ufetchrow('SELECT group_name FROM '.$prefix.'_bbgroups WHERE group_id='.($this->view-3));
			$error = '<i>'.$groupName.'</i> '._MODULESGROUPS;
		}
		if (isset($error)) {
			if ($check) { return $error; }
			cpg_error($error, E_USER_ERROR);
		}
		return true;
	}

	# $title: string to search by name
	# return bool
	public function is_active($name)
	{
		$name = strtolower($name);
		return isset($this->list[$name]) && $this->list[$name]['active'] ;
		//return is_array(page_data($name));
	}

	# $id: integer to search by id or string to search by name
	# return bool
	public function exist($title)
	{
		return isset($this->list[$title]);
	}

	public static function set_title($title)
	{
		if (defined('_'. $title))             { $title = constant('_'. $title); }
		elseif (defined('_'. $title. 'LANG')) { $title = constant('_'. $title. 'LANG'); }
		else                                  { $title = ucwords(str_replace('_', ' ', $title)); }
		return $title;
	}

	private function loadAdmin()
	{
		$this->mid   = -1;
		$this->pos   = -1;
		$this->chroot = ADMIN_PATH.'modules'.DS;
		$this->sides = is_admin() ? Blocks::ALL : Blocks::NONE;
		if (is_file(ADMIN_PATH.'modules'.DS.$this->name.'.php')) {
			$this->file = $this->name.'.php';
		}
		else if (is_file(MODULE_PATH.$this->name.DS.'admin'.DS.$this->file.'.inc')) {
			$this->chroot = MODULE_PATH.$this->name.DS.'admin'.DS;
			$this->file = $this->file.'.inc';
		} else {
			$this->name  = 'admin';
			$this->file  = 'index.php';
		}
		get_lang($this->name, -1);
		$this->title = self::set_title(_ADMINISTRATION);
	}

	private function loadModule()
	{
		global $prefix, $db, $MAIN_CFG;
		// temporary path for custom.inc, location and/or name may change in future, not to be shipped with df
		//if (is_file(MODULE_PATH.'custom.inc')) {
		//	require_once(MODULE_PATH.'custom.inc');
			foreach(self::$custom as $i => $this->data){
				if ($this->name == self::$custom[$i]['get']) { break; }
				$this->data = array();
			}
			self::$custom = array();
		//}
		if ($this->data) {
			$this->chroot = BASEDIR;
			$this->file   = $this->data['file'];
			$this->name   = $this->data['title'];
			$this->active = true;
		}
		else {
			$this->data = $db->uFetchAssoc("SELECT * FROM {$prefix}_modules WHERE title='".strtolower($this->name)."'");
			if ($this->data) {
				$this->chroot = MODULE_PATH.$this->data['title'].DS;
				$this->file   = $this->file.'.php';
				$this->name   = $this->data['title'];
				$this->active = (bool)$this->data['active'];
			}
		}
		if (!$this->data) { return; }
		get_lang($this->name, -1);
		$this->mid       =  (int)$this->data['mid'];//required
		$this->sides     =  Blocks::$showblocks = (int)$this->data['blocks'];//required
		$this->view      =  (int)$this->data['view'];//required
		$this->cat_id    = isset($this->data['cat_id'])  ?   (int)$this->data['cat_id']   : null;
		$this->inmenu    = isset($this->data['inmenu'])  ?  (bool)$this->data['inmenu']   : null;
		$this->pos       = isset($this->data['pos'])     ?   (int)$this->data['pos']      : null;
		$this->uninstall = isset($this->data['unistall'])?  (bool)$this->data['uninstall']: null;
		$this->version   = isset($this->data['version']) ? (float)$this->data['version']  : null;
		$this->name_lc   = strtolower($this->data['title']);
		$this->in_home   = $this->name_lc == strtolower($MAIN_CFG['global']['main_module']);
		$this->title     = self::set_title($this->data['title']);
	}

	private function push($data)
	{
		if (!preg_match('#^([a-zA-Z0-9_\-]+)$#', $data['name'])) {
			cpg_error(sprintf(_ERROR_BAD_CHAR, strtolower(_MODULES)), E_USER_ERROR);
		}
		if (isset($this->list[$data['name']])) {
			trigger_error($data['name'].': Module name already taken.', E_USER_WARNING);
			return;
		}
		$data['title'] = self::set_title($data['name']);
		$this->list[$data['name']] = $data;
		return true;
	}

}
